package com.example.springstack.springboot.mongo.init.config;

import com.exampl.springstack.common.GlobalConst;
import com.example.springstack.springboot.mongo.init.entity.Parameters;
import com.example.springstack.springboot.mongo.init.service.ParametersService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * 初始化mongodbSql语句
 * @author qiangfanghao
 * @date
 */
@Slf4j
@Configuration
public class UpdateSqlInit implements InitializingBean {


    @Autowired
    private ParametersService parametersService;

    @Autowired()
    @Qualifier("mongoTemplateMajor")
    private MongoTemplate mongoTemplate;

    @Autowired
    private ApplicationContext applicationContext;

    /**
     * springboot项目 打jar包之后无法获取 classpath路径下的文件
     *  private final String initFilePath = "classpath:init/mongoInit.sql"
     */
    private final String initFilePath = "/init/mongoInit.sql";

    private List<String> lineList = new ArrayList<String>();


    @Override
    public void afterPropertiesSet() throws Exception {


        try{
            log.debug("初始化sql开始");
            //获取sql文件终端版本号
            String version = getVersion();
            if(StringUtils.isBlank(version)){
                throw new RuntimeException("版本号为空初始化失败");
            }
            //初始化sql
            Initialize(version);

        }catch(Exception e){
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }


    /**
     * 初始化sql
     * @param version
     */
    private void Initialize(String version){

        //获取到 初始化参数中
        Parameters parameters = parametersService.findOneByName("dbupdate");

        if (parameters != null){
            String value = parameters.getValue();
            //如果 value与 version 不等 则进行初始化
            if (!value.equalsIgnoreCase(version)){
                mongoSqlInitialize();
                //更新项目版本号
                parameters.setValue(version);
                this.parametersService.save(parameters);
            }else {
                log.debug("版本号检索成功,不进行MongoSql初始化");
            }
        }else {
            //更新mongosql语句
            mongoSqlInitialize();

            Parameters tempParameter = new Parameters();
            tempParameter.setName("dbupdate");
            tempParameter.setValue(version);
            //不可见
            tempParameter.setVisible(GlobalConst.INVISIBLE);
            tempParameter.setUpdatable(GlobalConst.VISIBLE);

            this.parametersService.save(tempParameter);
        }
    }

    /**
     * 初始化 .sql文件内容
     */
    private void mongoSqlInitialize(){
        try {
            List<StringBuffer> documents = resolveDocuments();
            for (StringBuffer sbu : documents) {
                Document document = this.mongoTemplate.executeCommand(sbu.toString());
                log.debug("该版本的数据库升级sql执行结果:{}", document);
            }
            log.debug("该版本数据库升级sql初始化完成标记.");

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

    /**
     * 获取 mongoInit版本号
     * @return
     */
    private String getVersion(){
        List<String> list = getLineList();
        if(list.isEmpty()){
            return null;
        }
        String line = list.get(0).trim();
        return line.substring("--".length()).trim();
    }

    private List<String> getLineList() {
        try {
            if(lineList.isEmpty()){
//                org.springframework.core.io.Resource res = this.applicationContext.getResource(initFilePath);
                //根据文件路径获取input流 获取到文件内容 springboot jar包中 无法根据classpath获取
                ClassPathResource res = new ClassPathResource(initFilePath);
                InputStream inputStream = res.getInputStream();
                if(!res.exists()){
                    log.error("找不到系统初始化文件:{}", "mongoInit.sql");
                    throw new RuntimeException();
                }
//                lineList = FileUtils.readLines(res.getFile(), "utf-8");

                lineList = IOUtils.readLines(inputStream,"utf-8");
                inputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return lineList;
    }

    /**
     * 提取初始化语句
     * @return
     */
    private List<StringBuffer> resolveDocuments(){
        //保存要初始化的文档v
        List<StringBuffer> docList = new ArrayList<StringBuffer>();
        List<String> list = getLineList();
        StringBuffer sbu = new StringBuffer();
        for (String line : list) {
            line = line.trim();
            //--用于注释
            if(StringUtils.isBlank(line) || line.startsWith("--")){
                continue;
            }
            sbu.append(line);
            //分号匹配文档的结束
            if(line.endsWith(";")){
                //如果文档没内容，只包含分号则忽略
                if(!sbu.toString().equals(";")){
                    docList.add(sbu);
                }
                sbu = new StringBuffer();
            }
        }
        log.debug("该版本的数据库升级要初始化文档数量={}", docList.size());
        return docList;
    }

}
